#include "usart1.h"
#include "string.h"

#include "stm32f10x_rcc.h"
#include "stm32f10x_gpio.h"
#include "stm32f10x_usart.h"

#ifndef NULL
#define NULL			((void *)0)
#endif

static void usart1_send_char(unsigned char a)
{
	USART_SendData(USART1, (unsigned char)a);
	while (!(USART1->SR & USART_FLAG_TXE));
}

static void usart1_send_string(unsigned char *str)
{
	if(NULL != str)
	{
		while(*str)
		{
			usart1_send_char(*str++);
		}
	}
}

static void usart1_send_int(int val, int mode)
{
	unsigned char buffer[32] = {0};
	usart1_send_string(itoa_r(val, mode, buffer, sizeof(buffer)));
}

static void usart_send_array(void *array, int num, int type, int mode)
{
	int i = 0;
	switch(type)
	{
		case 1:
			for(i = 0; i < num; i++)
			{
				usart1_send_int(((unsigned char *)array)[i], mode);
				if(i != num - 1)
				{
					usart1_send_string(", ");
				}
			}
			break;
		case 2:
			for(i = 0; i < num; i++)
			{
				usart1_send_int(((unsigned short *)array)[i], mode);
				if(i != num - 1)
				{
					usart1_send_string(", ");
				}
			}
			break;
		case 4:
			for(i = 0; i < num; i++)
			{
				usart1_send_int(((unsigned int *)array)[i], mode);
				if(i != num - 1)
				{
					usart1_send_string(", ");
				}
			}
			break;
		default:
			//usart1_send_string("bad type!!!\r\n");
			break;
	}
}

static void usart1_send_crlf(int num)
{
	for(int i = 0; i < num; i++)
	{
		usart1_send_char(0xA);
		usart1_send_char(0xD);
	}
}

static void usart1_send_mem(unsigned char *data, unsigned int len)
{
	int i = 0;
	usart1_send_crlf(1);
	for(i = 0; i < len; i++)
	{
		if(0 == i % 16)
		{
			usart1_send_char(i / 16 + '0');
			usart1_send_char(':');
			usart1_send_char(0x20);
		}
		if(0xF >= data[i])
		{
			usart1_send_char('0');
		}
		usart1_send_int(data[i], 2);
		if(0 == (i + 1) % 16)
		{
			usart1_send_char(0xA);
			usart1_send_char(0xD);
		}
		else if(0 == (i + 1) % 8)
		{
			usart1_send_char(0x9);
		}
		else
		{
			usart1_send_char(0x20);
		}
	}
	usart1_send_crlf(2);
}

static void usart1_gpio_init(void)
{
	GPIO_InitTypeDef GPIO_InitStructure;
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1 | RCC_APB2Periph_GPIOA, ENABLE);

	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
	GPIO_Init(GPIOA, &GPIO_InitStructure);

	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
	GPIO_Init(GPIOA, &GPIO_InitStructure);
}

static void usart1_usart_init(void)
{
	USART_InitTypeDef USART_InitStructure;

	USART_Cmd(USART1, DISABLE);
	USART_InitStructure.USART_BaudRate = 115200;
	USART_InitStructure.USART_WordLength = USART_WordLength_8b;
	USART_InitStructure.USART_StopBits = USART_StopBits_1;
	USART_InitStructure.USART_Parity = USART_Parity_No;
	USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
	USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
	USART_Init(USART1, &USART_InitStructure);
	USART_Cmd(USART1, ENABLE);
	
}

static USART1_INTERFACE_T _obj_usart1 = {
	.send_char = usart1_send_char,
	.send_string = usart1_send_string,
	.send_int = usart1_send_int,
	.send_array = usart_send_array,
	.send_crlf = usart1_send_crlf,
	.send_mem = usart1_send_mem
};

void usart1_init(void)
{
	usart1_gpio_init();
	usart1_usart_init();
	usart1_send_string("\r\n\r\n\r\n\r\n\r\n\r\nUSART1 is ready!!!\r\n");
}

void usart1_get_interface(USART1_INTERFACE_P *obj)
{
	*obj = &_obj_usart1;
}